<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/2/28 0028
 * Time: 9:46
 */
namespace app\wx_api\ext\we_chat;

use app\common\helper\RequestByCurl;
use think\Cache;

/**
 * 微信处理access_token的中控服务器
 * 实际项目应该把这块独立出去作为一个
 * 单独的项目和服务器，用redis等其他更
 * 高效的缓存工具进行所有微信账号的通用
 * access_token的管理，小项目直接嵌入项目
 * 中用文件缓存得了。
 *
 * Class AccessTokenCache
 * @package app\wx_api\ext\we_chat
 */
class AccessTokenCache implements AccessTokenInterface {
    public $err_msg = null;
    const PREFIX_CACHE_TOKEN = 'access_token_';
    const WX_ACCESS_TOKEN_API = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s';

    private $_cache = null;

    private $_config = [
        // 驱动方式
        'type'   => 'file',
        // 缓存保存目录
        'path'   => '../runtime/cache/token/',
        // 缓存前缀
        'prefix' => 'file_cache',
        // 缓存有效期 0表示永久缓存
        'expire' => 0,
    ];

    public function __construct($config = null)
    {
        if ($config) {
            $cacheM = new Cache($config);
        } else {
            $cacheM = new Cache($this->_config);
        }
        $this->_cache = $cacheM;
    }

    /**
     * 获取微信通用access_token
     * @param int $wx_id 注册在平台的微信账户ID
     * @return bool|mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function getAccessToken($wx_id) {
        $wx_config = WXConfig::wxConfig($wx_id);
        if (empty($wx_config)) {
            $this->err_msg = '没有找到对应的微信账户信息';
            return false;
        }
        $original_id = $wx_config['original_id'];
        $name = self::PREFIX_CACHE_TOKEN . $original_id;
        $token_cache = $this->_cache->get($name);
        if ($token_cache) { // have cache
            //var_dump('cache:', $permission_cache);die;
            return $token_cache;
        } else { // 调用微信接口获取token
            if ($token = $this->requestAccessToken($wx_id)) {
                return $token;
            }
        }
        // no cache
        $this->err_msg = '获取口令失败';
        return false;
    }

    /**
     * 请求微信通用token
     *
     * @param $wx_id
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function requestAccessToken($wx_id) {
        $wx_config = WXConfig::wxConfig($wx_id);
        $url = sprintf(self::WX_ACCESS_TOKEN_API, $wx_config['app_id'], $wx_config['secret']);
        $res = RequestByCurl::https_request($url);
        $res = json_decode($res, true);
        if (isset($res['errcode'])) {
            $this->err_msg = 'errcode:' . $res['errcode'] . ',errormsg:' . $res['errmsg'];
            return false;
        }
        if ($this->setToken($wx_config['original_id'], $res['access_token'], $res['expires_in'])) {
            return $res['access_token'];
        }
        return false;
    }


    /**
     * 保存token到缓存
     * @param $original_id
     * @param $token
     * @param $expires_in
     * @return bool
     */
    public function setToken($original_id, $token, $expires_in) {
        //$cacheM = new Cache();
        $name = self::PREFIX_CACHE_TOKEN . $original_id;
        if ($this->_cache->set($name, $token, $expires_in-300)) {
            return true;
        }
        // failure
        $this->err_msg = '缓存token失败';
        return false;
    }

    /**
     * 清除token缓存
     *
     * @return bool
     */
    public function rmAccessToken() {
        return $this->_cache->clear();
    }


}